var debugVertexShaderStr = "\
attribute vec3 inPosition;\
uniform mat4 modelViewProjectionMat;\
void main(void)\
{\
  gl_PointSize = 4.0;\
  gl_Position = modelViewProjectionMat*vec4(inPosition, 1.0);\
}\
";
var debugFragmentShaderStr = "\
uniform vec4 inColor;\
void main(void)\
{\
  gl_FragColor = inColor;\
}\
";
function drawAabb(gl, debugDrawer, aabb,color,isSolid)
{
  if(color)
    gl.uniform4f(debugDrawer.inColor,color.x,color.y,color.z,1.);
  var pos = new WebGLFloatArray(8 * 3);
  var min = aabb.min;
  var max = aabb.max;
  pos[0] = min.x;
  pos[1] = min.y;
  pos[2] = min.z;
  pos[3] = max.x;
  pos[4] = min.y;
  pos[5] = min.z;
  pos[6] = max.x;
  pos[7] = min.y;
  pos[8] = max.z;
  pos[9] = min.x;
  pos[10] = min.y;
  pos[11] = max.z;
  pos[12] = min.x;
  pos[13] = max.y;
  pos[14] = min.z;
  pos[15] = max.x;
  pos[16] = max.y;
  pos[17] = min.z;
  pos[18] = max.x;
  pos[19] = max.y;
  pos[20] = max.z;
  pos[21] = min.x;
  pos[22] = max.y;
  pos[23] = max.z;
 
  if(isSolid==true)
    var indices = new WebGLUnsignedShortArray([0,1,2,2,3,0, 1,2,5,2,5,6, 2,3,7,2,6,7, 1,0,5,0,5,4, 4,5,6,6,4,7, 0,3,4,3,4,7]);
  else
    var indices = new WebGLUnsignedShortArray([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7]);
    
  var glbuf = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, glbuf);
  gl.bufferData(gl.ARRAY_BUFFER, pos, gl.STREAM_DRAW);
  gl.vertexAttribPointer(debugDrawer.inPosition, 3, gl.FLOAT, false, 0, 0);
  var indexbuf = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexbuf);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
  if(isSolid==true)
    gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
  else
    gl.drawElements(gl.LINES, 24, gl.UNSIGNED_SHORT, 0);
  gl.deleteBuffer(glbuf);
  gl.deleteBuffer(indexbuf);
  
}

function drawBatch(gl, debugDrawer, batch)
{
  var nodeList = batch.nodeList;
  var nodeNum = nodeList.length;
  var pos = new WebGLFloatArray(nodeNum * 3 + 3);
  pos[0] = batch.center.x;
  pos[1] = batch.center.y;
  pos[2] = batch.center.z;
  for (var i = 0; i < nodeNum; i++) 
  {
    var nodeCenter = nodeList[i].worldSphere.center;
    pos[3 + i * 3] = nodeCenter.x;
    pos[3 + i * 3 + 1] = nodeCenter.y;
    pos[3 + i * 3 + 2] = nodeCenter.z;
  }
  var indices = new WebGLUnsignedShortArray(nodeNum * 2);
  for (var i = 0; i < nodeNum; i++) 
  {
      indices[i*2] = 0; 
      indices[i*2+1] = i + 1;
  }
  var glbuf = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, glbuf);
  gl.bufferData(gl.ARRAY_BUFFER, pos, gl.STREAM_DRAW);
  gl.vertexAttribPointer(debugDrawer.inPosition, 3, gl.FLOAT, false, 0, 0);
  var indexbuf = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexbuf);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
  gl.drawElements(gl.LINES, nodeNum * 2, gl.UNSIGNED_SHORT, 0);
  gl.deleteBuffer(glbuf);
  gl.deleteBuffer(indexbuf);
}
// verticesArray is a WebGLFloatArray that contain all point we want to draw
// indices is optional
function drawVerticesAsPoint(gl, debugDrawer, verticesArray, num,indices) 
{
  gl.enable(0x8642);
  if(indices == undefined|| indices==null)
  {
    var indices = new WebGLUnsignedShortArray(num);
    for (var i = 0; i < num; i++) 
    {
        indices[i] = i; 
    }
  }
  var glbuf = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, glbuf);
  gl.bufferData(gl.ARRAY_BUFFER, verticesArray, gl.STREAM_DRAW);
  gl.vertexAttribPointer(debugDrawer.inPosition, 3, gl.FLOAT, false, 0, 0);
  var indexbuf = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexbuf);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
  gl.drawElements(gl.POINTS, num, gl.UNSIGNED_SHORT, 0);
  gl.deleteBuffer(glbuf);
  gl.deleteBuffer(indexbuf);
  gl.disable(0x8642);
}
function drawPrimitives(gl, debugDrawer, verticesArray, num,indices,type,offset) 
{
  var glbuf = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, glbuf);
  gl.bufferData(gl.ARRAY_BUFFER, verticesArray, gl.STREAM_DRAW);
  gl.vertexAttribPointer(debugDrawer.inPosition, 3, gl.FLOAT, false, 0, 0);
  var indexbuf = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexbuf);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
  if(offset)
    gl.drawElements(type, num, gl.UNSIGNED_SHORT, offset);
  else
    gl.drawElements(type, num, gl.UNSIGNED_SHORT, 0);
  gl.deleteBuffer(glbuf);
  gl.deleteBuffer(indexbuf);
  gl.disable(0x8642);
}
function drawGrid(gl,debugDrawer,size)
{
  var ver_num = (2*size+1)*4;
  var ver = new WebGLFloatArray(ver_num*3);
  var ind = new WebGLUnsignedShortArray(ver_num);
  
  var offset = 0;
  for(var i=-size;i<=size;i++)
  {
    ver[offset]   = i;
    ver[offset+1] = 0;
    ver[offset+2] = -size;
    
    ver[offset+3]   = i;
    ver[offset+4] = 0;
    ver[offset+5] = size;
    
    ver[offset+6]   = -size;
    ver[offset+7] = 0;
    ver[offset+8] = i;
    
    ver[offset+9] = size;
    ver[offset+10] = 0;
    ver[offset+11] = i;
    offset+=12;
  }
  for(var i=0;i< ver_num;i++)
  {
    ind[i] = i;
  }
  drawPrimitives(gl, debugDrawer, ver, ver_num,ind,gl.LINES); 
}
function drawNavigator(scene3d)
{
  var drawer = scene3d.debugDrawer;
  if(!drawer)
  {
    var gl = scene3d.gl;
    scene3d.debugDrawer = {};
    scene3d.debugDrawer.vs = createVertexShader(gl, debugVertexShaderStr);
    scene3d.debugDrawer.fs = createFragmentShader(gl,debugFragmentShaderStr);
    var program = gl.createProgram();
    gl.attachShader(program,scene3d.debugDrawer.vs);
    gl.attachShader(program,scene3d.debugDrawer.fs);
    gl.linkProgram(program);
    checkProgramLinkStatus(gl,program);
    scene3d.debugDrawer.program = program;
    scene3d.debugDrawer.inPosition = gl.getAttribLocation(program, "inPosition");
    scene3d.debugDrawer.modelViewProjectionMat = gl.getUniformLocation(program, "modelViewProjectionMat");
    scene3d.debugDrawer.inColor = gl.getUniformLocation(program, "inColor");
  }
  gl.useProgram(drawer.program);
  gl.enable(gl.DEPTH_TEST);
  gl.enableVertexAttribArray(drawer.inPosition);
  gl.uniformMatrix4fv(drawer.modelViewProjectionMat, false, this.viewProjectMat.data);
  gl.uniform4f(drawer.inColor,1.,0.,0.,1.);
  
  
}
function circleTable(sint,cost,n)
{
  var i;
  /* Table size, the sign of n flips the circle direction */
  var size = Math.abs(n);
  /* Determine the angle between samples */
  var angle = 2* 3.14/n;
  /* Compute cos and sin around the circle */
  for(i=0; i<size; i++)
  {
    sint[i] = Math.sin(angle*i);
    cost[i] = Math.cos(angle*i);
  }
  /* Last sample is duplicate of the first */
  sint[size] = sint[0];
  cost[size] = cost[0];
}
function drawCone(gl,debugDrawer,radius,stacks,height,color)
{
  if(color)
    gl.uniform4f(debugDrawer.inColor,color.x,color.y,color.z,1.);
  var sint1 = [],cost1 = [];
  circleTable(sint1,cost1, stacks);
  var ver = [];
  
  ver.push(0,0,0);
  ver.push(0,height,0);
  var ind1 = [];
  var ind2 = [];
  ind1.push(0);
  ind2.push(1);
  for (i=1; i<stacks; i++)
  {
    ver.push(sint1[i]*radius,0,cost1[i]*radius);
    ind1.push(i+1);
    ind2.push(i+1);
  }
  ind2.push(2);
  var verbuf = new WebGLFloatArray(ver);
  var ind1buf = new WebGLUnsignedShortArray(ind1);
  var ind2buf = new WebGLUnsignedShortArray(ind2);
  
  drawPrimitives(gl,debugDrawer,verbuf,ind1.length,ind1buf,gl.TRIANGLE_FAN);
  drawPrimitives(gl,debugDrawer,verbuf,ind2.length,ind2buf,gl.TRIANGLE_FAN);    
  
  delete verbuf;
  delete ind1buf;
  delete ind2buf;
}
function drawWireSphere(gl,debugDrawer,center,radius,slices,stacks)
{
  var i,j;
  /* Adjust z and radius as stacks and slices are drawn. */
  var r;
  var x,y,z;
  /* Pre-computed circle */
  var sint1 = [],cost1 = [];
  var sint2 = [],cost2 = [];
  circleTable(sint1,cost1,-slices  );
  circleTable(sint2,cost2, stacks*2);
  /* Draw a line loop for each stack */
  var ver = [];
  for (i=1; i<stacks; i++)
  {
    z = cost2[i];
    r = sint2[i];
    for(j=0; j<=(slices-1); j++)
    {
      x = cost1[j];
      y = sint1[j];
      ver.push(x*r*radius +center.x);
      ver.push(y*r*radius+center.y);
      ver.push(z*radius+center.z);
      
      x = cost1[j+1];
      y = sint1[j+1];
      ver.push(x*r*radius +center.x);
      ver.push(y*r*radius+center.y);
      ver.push(z*radius+center.z);      
    }
  }
  for (i=0; i<slices; i++)
  {
    for(j=0; j<=stacks; j++)
    {
      x = cost1[i]*sint2[j];
      y = sint1[i]*sint2[j];
      z = cost2[j];      
      ver.push(x*radius+center.x);
      ver.push(y*radius+center.y);
      ver.push(z*radius+center.z);
      
      x = cost1[i]*sint2[j+1];
      y = sint1[i]*sint2[j+1];
      z = cost2[j+1];      
      ver.push(x*radius+center.x);
      ver.push(y*radius+center.y);
      ver.push(z*radius+center.z);
    }
  }
  var glbuf = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, glbuf);
  gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(ver), gl.STATIC_DRAW);
  gl.vertexAttribPointer(debugDrawer.inPosition, 3, gl.FLOAT, false, 0, 0);
  gl.drawArrays(gl.LINES, 0, ver.length/3);
  gl.deleteBuffer(glbuf);
}
